package com.jeesite.common.utils.weixin;

import com.jeesite.modules.config.web.WeixinProperties;
import com.jeesite.modules.fl.utils.FlConstants;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.concurrent.ConcurrentHashMap;

public class WeixinUserInterceptor extends HandlerInterceptorAdapter {

  private WxMpService wxMpService;
  private WeixinProperties weixinProperties;

  public WeixinUserInterceptor(WxMpService wxMpService, WeixinProperties weixinProperties) {
    this.wxMpService = wxMpService;
    this.weixinProperties = weixinProperties;
  }

  private ConcurrentHashMap<Method, Boolean> checkMap = new ConcurrentHashMap<>();
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    if (handler instanceof HandlerMethod) {
      HandlerMethod hm = (HandlerMethod) handler;
      Method m = hm.getMethod();
      Boolean flag;
      if (checkMap.containsKey(m)) {
        flag = checkMap.get(m);
      } else {
        flag = resolveFlag(hm);
      }
      if (flag) {
        Object obj = request.getSession().getAttribute(FlConstants.SESS_OPEN_ID);
        if (obj == null) {
          String encRequestUri = URLEncoder.encode(request.getRequestURI(), "UTF-8");
          response.sendRedirect(
              wxMpService.oauth2buildAuthorizationUrl(
                  weixinProperties.getRedirectUrl()+"&rurl="+encRequestUri,
                  WxConsts.OAuth2Scope.SNSAPI_USERINFO,
                  null // 以后可以考虑加上 数据 以便 返回到响应的功能模块
              ));
          return false;
        }
      }
    }
    return super.preHandle(request, response, handler);
  }

  private Boolean resolveFlag(HandlerMethod hm) {
    RequireWeixin classAnno = AnnotationUtils.findAnnotation(hm.getBean().getClass(), RequireWeixin.class);
    RequireWeixin methodAnno = AnnotationUtils.findAnnotation(hm.getMethod(), RequireWeixin.class);
    Boolean flag =  classAnno != null || methodAnno != null;
    checkMap.put(hm.getMethod(), flag);
    return flag;
  }
}
